GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/zserio/ArrayTest.cpp Lines: 671 671 100.0 %
Date: 2023-10-04 12:47:22 Branches: 16347 57461 28.4 %

Line Branch Exec Source
1
#include <string>
2
#include <vector>
3
#include <limits>
4
#include <array>
5
6
#include "gtest/gtest.h"
7
8
#include "zserio/Array.h"
9
#include "zserio/ArrayTraits.h"
10
#include "zserio/Enums.h"
11
#include "zserio/CppRuntimeException.h"
12
#include "zserio/BitBuffer.h"
13
14
#include "test_object/std_allocator/ArrayBitmask.h"
15
#include "test_object/std_allocator/ArrayEnum.h"
16
#include "test_object/std_allocator/ArrayObject.h"
17
18
namespace zserio
19
{
20
21
using ArrayEnum = test_object::std_allocator::ArrayEnum;
22
using ArrayBitmask = test_object::std_allocator::ArrayBitmask;
23
using ArrayObject = test_object::std_allocator::ArrayObject;
24
25
namespace
26
{
27
28
class ArrayTestOwner
29
{};
30
31
class ArrayTestOwnerWithBitSize
32
{
33
public:
34
7
    explicit ArrayTestOwnerWithBitSize(uint8_t bitSize) :
35
7
            m_bitSize(bitSize)
36
7
    {}
37
38
3446
    uint8_t getBitSize() const
39
    {
40
3446
        return m_bitSize;
41
    }
42
43
private:
44
    uint8_t m_bitSize;
45
};
46
47
template <typename ARRAY, typename OWNER_TYPE>
48
272
size_t arrayBitSizeOf(const ARRAY& array, const OWNER_TYPE& owner, size_t bitPosition)
49
{
50
272
    return array.bitSizeOf(owner, bitPosition);
51
}
52
53
template <typename ARRAY>
54
2113
size_t arrayBitSizeOf(const ARRAY& array, const detail::DummyArrayOwner&, size_t bitPosition)
55
{
56
2113
    return array.bitSizeOf(bitPosition);
57
}
58
59
template <typename ARRAY, typename OWNER_TYPE>
60
64
size_t arrayBitSizeOfPacked(const ARRAY& array, const OWNER_TYPE& owner, size_t bitPosition)
61
{
62
64
    return array.bitSizeOfPacked(owner, bitPosition);
63
}
64
65
template <typename ARRAY>
66
800
size_t arrayBitSizeOfPacked(const ARRAY& array, const detail::DummyArrayOwner&, size_t bitPosition)
67
{
68
800
    return array.bitSizeOfPacked(bitPosition);
69
}
70
71
template <typename ARRAY, typename OWNER_TYPE>
72
272
size_t arrayInitializeOffsets(ARRAY& array, OWNER_TYPE& owner, size_t bitPosition)
73
{
74
272
    return array.initializeOffsets(owner, bitPosition);
75
}
76
77
template <typename ARRAY>
78
2113
size_t arrayInitializeOffsets(ARRAY& array, detail::DummyArrayOwner&, size_t bitPosition)
79
{
80
2113
    return array.initializeOffsets(bitPosition);
81
}
82
83
template <typename ARRAY, typename OWNER_TYPE>
84
64
size_t arrayInitializeOffsetsPacked(ARRAY& array, OWNER_TYPE& owner, size_t bitPosition)
85
{
86
64
    return array.initializeOffsetsPacked(owner, bitPosition);
87
}
88
89
template <typename ARRAY>
90
800
size_t arrayInitializeOffsetsPacked(ARRAY& array, detail::DummyArrayOwner&, size_t bitPosition)
91
{
92
800
    return array.initializeOffsetsPacked(bitPosition);
93
}
94
95
template <typename ARRAY, typename OWNER_TYPE>
96
272
void arrayRead(ARRAY& array, OWNER_TYPE& owner, BitStreamReader& in, size_t arrayLength = 0)
97
{
98
272
    array.read(owner, in, arrayLength);
99
272
}
100
101
template <typename ARRAY>
102
2113
void arrayRead(ARRAY& array, detail::DummyArrayOwner&, BitStreamReader& in, size_t arrayLength = 0)
103
{
104
2113
    array.read(in, arrayLength);
105
2112
}
106
107
template <typename ARRAY, typename OWNER_TYPE>
108
64
void arrayReadPacked(ARRAY& array, OWNER_TYPE& owner, BitStreamReader& in, size_t arrayLength = 0)
109
{
110
64
    array.readPacked(owner, in, arrayLength);
111
64
}
112
113
template <typename ARRAY>
114
800
void arrayReadPacked(ARRAY& array, detail::DummyArrayOwner&, BitStreamReader& in, size_t arrayLength = 0)
115
{
116
800
    array.readPacked(in, arrayLength);
117
800
}
118
119
template <typename ARRAY, typename OWNER_TYPE>
120
272
void arrayWrite(const ARRAY& array, const OWNER_TYPE& owner, BitStreamWriter& out)
121
{
122
272
    array.write(owner, out);
123
272
}
124
125
template <typename ARRAY>
126
2113
void arrayWrite(const ARRAY& array, const detail::DummyArrayOwner&, BitStreamWriter& out)
127
{
128
2113
    array.write(out);
129
2113
}
130
131
template <typename ARRAY, typename OWNER_TYPE>
132
64
void arrayWritePacked(const ARRAY& array, const OWNER_TYPE& owner, BitStreamWriter& out)
133
{
134
64
    array.writePacked(owner, out);
135
64
}
136
137
template <typename ARRAY>
138
800
void arrayWritePacked(const ARRAY& array, const detail::DummyArrayOwner&, BitStreamWriter& out)
139
{
140
800
    array.writePacked(out);
141
800
}
142
143
class ElementBitSizeWithOwner
144
{
145
public:
146
    using OwnerType = ArrayTestOwnerWithBitSize;
147
148
3446
    static uint8_t get(const ArrayTestOwnerWithBitSize& owner)
149
    {
150
3446
        return owner.getBitSize();
151
    }
152
};
153
154
template <uint8_t BIT_SIZE>
155
class ElementBitSizeWithoutOwner
156
{
157
public:
158
2630
    static uint8_t get()
159
    {
160
2630
        return BIT_SIZE;
161
    }
162
};
163
164
class ArrayObjectArrayExpressions
165
{
166
public:
167
    using OwnerType = ArrayTestOwner;
168
169
48
    static void initializeOffset(ArrayTestOwner&, size_t, size_t)
170
48
    {}
171
172
96
    static void checkOffset(const ArrayTestOwner&, size_t, size_t)
173
96
    {}
174
175
3
    static void initializeElement(ArrayTestOwner&, ArrayObject& element, size_t)
176
    {
177
        // set value instead of call initialize, just for test
178
3
        element.setValue(ELEMENT_VALUE);
179
3
    }
180
181
    static const uint32_t ELEMENT_VALUE = 0x12;
182
};
183
184
class ArrayObjectElementFactory
185
{
186
public:
187
    using OwnerType = ArrayTestOwner;
188
    using allocator_type = std::allocator<uint8_t>;
189
190
96
    static void create(OwnerType&, std::vector<ArrayObject>& array, BitStreamReader& in, size_t)
191
    {
192
96
        array.emplace_back(in, array.get_allocator());
193
96
    }
194
195
96
    static void create(OwnerType&, std::vector<ArrayObject>& array,
196
            ArrayObject::ZserioPackingContext& contextNode, BitStreamReader& in, size_t)
197
    {
198
96
        array.emplace_back(contextNode, in, array.get_allocator());
199
96
    }
200
};
201
202
} // namespace
203
204
59
class ArrayTest : public ::testing::Test
205
{
206
public:
207
59
    ArrayTest() :
208
59
            m_byteBuffer()
209
59
    {}
210
211
protected:
212
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
213
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
214
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type,
215
            typename std::enable_if<!std::is_integral<OWNER_TYPE>::value, int>::type = 0>
216
53
    void testArray(const RAW_ARRAY& rawArray, size_t elementBitSize, OWNER_TYPE owner = OWNER_TYPE())
217
    {
218
53
        const size_t arraySize = rawArray.size();
219
53
        const size_t unalignedBitSize = elementBitSize * arraySize;
220
        const size_t alignedBitSize = (arraySize > 0)
221
37
                ? alignTo(8, elementBitSize) * (arraySize - 1) + elementBitSize
222


















90
                : 0;
223
53
        testArray<ARRAY_TRAITS>(rawArray, unalignedBitSize, alignedBitSize, owner);
224
52
    }
225
226
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
227
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
228
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
229
71
    void testArray(const RAW_ARRAY& rawArray, size_t unalignedBitSize, size_t alignedBitSize,
230
            OWNER_TYPE owner = OWNER_TYPE())
231
    {
232
71
        testArrayNormal<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, unalignedBitSize, owner);
233
70
        testArrayAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
234
                rawArray, AUTO_LENGTH_BIT_SIZE + unalignedBitSize, owner);
235
70
        testArrayAligned<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, alignedBitSize, owner);
236
70
        testArrayAlignedAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
237
                rawArray, AUTO_LENGTH_BIT_SIZE + alignedBitSize, owner);
238
70
        testArrayImplicit<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(rawArray, unalignedBitSize, owner);
239
70
    }
240
241
    template <typename ARRAY_TRAITS, typename RAW_ARRAY>
242
1
    void testArrayInitializeElements(const RAW_ARRAY& rawArray)
243
    {
244
2
        Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ArrayObjectArrayExpressions> array(rawArray);
245
        ArrayTestOwner owner;
246
1
        array.initializeElements(owner);
247
1
        const uint32_t expectedValue = ArrayObjectArrayExpressions::ELEMENT_VALUE;
248

4
        for (const auto& element : array.getRawArray())
249



3
            ASSERT_EQ(expectedValue, element.getValue());
250
    }
251
252
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
253
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
254
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
255
17
    void testPackedArray(const RAW_ARRAY& rawArray, OWNER_TYPE owner = OWNER_TYPE())
256
    {
257
17
        testPackedArray<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
258
                rawArray, UNKNOWN_BIT_SIZE, UNKNOWN_BIT_SIZE, owner);
259
17
    }
260
261
    template <typename ARRAY_TRAITS, typename RAW_ARRAY,
262
            typename ARRAY_EXPRESSIONS = detail::DummyArrayExpressions,
263
            typename OWNER_TYPE = typename detail::array_owner_type<ARRAY_TRAITS, ARRAY_EXPRESSIONS>::type>
264
27
    void testPackedArray(const RAW_ARRAY& rawArray, size_t unalignedBitSize, size_t alignedBitSize,
265
            OWNER_TYPE owner = OWNER_TYPE())
266
    {
267
27
        testPackedArrayNormal<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
268
                rawArray, unalignedBitSize, owner);
269







27
        testPackedArrayAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
270
                rawArray, (unalignedBitSize != UNKNOWN_BIT_SIZE)
271
                        ? AUTO_LENGTH_BIT_SIZE + unalignedBitSize : UNKNOWN_BIT_SIZE, owner);
272
27
        testPackedArrayAligned<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
273
                rawArray, alignedBitSize, owner);
274







27
        testPackedArrayAlignedAuto<ARRAY_TRAITS, RAW_ARRAY, ARRAY_EXPRESSIONS>(
275
                rawArray, (alignedBitSize != UNKNOWN_BIT_SIZE)
276
                        ? AUTO_LENGTH_BIT_SIZE + alignedBitSize : UNKNOWN_BIT_SIZE, owner);
277
27
    }
278
279
1
    size_t calcPackedBitSize(size_t elementBitSize, size_t arraySize, size_t maxDeltaBitSize)
280
    {
281
1
        return PACKING_DESCRIPTOR_BITSIZE + elementBitSize + (arraySize - 1) * (maxDeltaBitSize + 1);
282
    }
283
284
1
    size_t calcAlignedPackedBitSize(size_t elementBitSize, size_t arraySize, size_t maxDeltaBitSize)
285
    {
286
1
        const size_t firstElementWithDescriptorBitSize = PACKING_DESCRIPTOR_BITSIZE + elementBitSize;
287
1
        const size_t alignedFirstElementWithDescriptorBitSize = (firstElementWithDescriptorBitSize + 7) / 8 * 8;
288
1
        const size_t alignedMaxDeltaBitSize = (maxDeltaBitSize + 1 + 7) / 8 * 8;
289
290
1
        return alignedFirstElementWithDescriptorBitSize +
291
2
                (arraySize - 2) * alignedMaxDeltaBitSize + (maxDeltaBitSize + 1);
292
    }
293
294
    static const size_t PACKING_DESCRIPTOR_BITSIZE = 1 + 6;
295
296
private:
297
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
298
71
    void testArrayNormal(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
299
    {
300
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ARRAY_EXPRESSIONS>;
301
302






















631
        for (uint8_t i = 0; i < 8; ++i)
303
        {
304






















1122
            ArrayT array(rawArray);
305
306






















561
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
307







































































































































561
            ASSERT_EQ(expectedBitSize, bitSize);
308





























































































































































561
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
309
310






















561
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
311






















561
            writer.writeBits(0, i);
312






















561
            arrayWrite(array, owner, writer);
313







































































































































561
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
314
315






















561
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
316





























































































































































561
            ASSERT_EQ(0, reader.readBits(i));
317























1122
            ArrayT readArray;
318






















561
            arrayRead(readArray, owner, reader, rawArray.size());
319







































































































































560
            ASSERT_EQ(array, readArray);
320
321













































560
            testArrayCopiesAndMoves(array);
322
        }
323
    }
324
325
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
326
70
    void testArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
327
    {
328
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
329
330






















630
        for (uint8_t i = 0; i < 8; ++i)
331
        {
332






















1120
            ArrayT array(rawArray);
333
334






















560
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
335







































































































































560
            ASSERT_EQ(expectedBitSize, bitSize);
336





























































































































































560
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
337
338






















560
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
339






















560
            writer.writeBits(0, i);
340






















560
            arrayWrite(array, owner, writer);
341







































































































































560
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
342
343






















560
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
344





























































































































































560
            ASSERT_EQ(0, reader.readBits(i));
345























1120
            ArrayT readArray;
346






















560
            arrayRead(readArray, owner, reader);
347







































































































































560
            ASSERT_EQ(array, readArray);
348
349













































560
            testArrayCopiesAndMoves(array);
350
        }
351
    }
352
353
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
354
70
    void testArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
355
    {
356
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
357
358






















630
        for (uint8_t i = 0; i < 8; ++i)
359
        {
360






















1120
            ArrayT array(rawArray);
361
362






















560
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
363






















560
            if (expectedBitSize == 0)
364
            {
365







































































































































200
                ASSERT_EQ(expectedBitSize, bitSize);
366
            }
367
            else
368
            {
369







































































































































360
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize);
370
            }
371





























































































































































560
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
372
373






















560
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
374






















560
            writer.writeBits(0, i);
375






















560
            arrayWrite(array, owner, writer);
376







































































































































560
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
377
378






















560
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
379





























































































































































560
            ASSERT_EQ(0, reader.readBits(i));
380























1120
            ArrayT readArray;
381






















560
            arrayRead(readArray, owner, reader, rawArray.size());
382







































































































































560
            ASSERT_EQ(array, readArray);
383
384













































560
            testArrayCopiesAndMoves(array);
385
        }
386
    }
387
388
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
389
70
    void testArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
390
    {
391
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
392
393






















630
        for (uint8_t i = 0; i < 8; ++i)
394
        {
395






















1120
            ArrayT array(rawArray);
396
397






















560
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
398
399






















560
            if (expectedBitSize == AUTO_LENGTH_BIT_SIZE)
400
            {
401







































































































































200
                ASSERT_EQ(expectedBitSize, bitSize);
402
            }
403
            else
404
            {
405





























































































































































360
                ASSERT_EQ(alignTo(8, i) - i + expectedBitSize, bitSize) << expectedBitSize;
406
            }
407





























































































































































560
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
408
409






















560
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
410






















560
            writer.writeBits(0, i);
411






















560
            arrayWrite(array, owner, writer);
412







































































































































560
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
413
414






















560
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
415





























































































































































560
            ASSERT_EQ(0, reader.readBits(i));
416























1120
            ArrayT readArray;
417






















560
            arrayRead(readArray, owner, reader);
418







































































































































560
            ASSERT_EQ(array, readArray);
419
420













































560
            testArrayCopiesAndMoves(array);
421
        }
422
    }
423
424
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
425
            typename std::enable_if<ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
426
40
    void testArrayImplicit(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
427
    {
428
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::IMPLICIT, ARRAY_EXPRESSIONS>;
429
430















40
        if (detail::arrayTraitsConstBitSizeOf<ARRAY_TRAITS>(owner) % 8 != 0)
431
22
            return; // implicit array allowed for types with constant bitsize rounded to bytes
432
433















162
        for (uint8_t i = 0; i < 8; ++i)
434
        {
435















288
            ArrayT array(rawArray);
436
437















144
            const size_t bitSize = arrayBitSizeOf(array, owner, i);
438


























































































144
            ASSERT_EQ(expectedBitSize, bitSize);
439









































































































144
            ASSERT_EQ(i + bitSize, arrayInitializeOffsets(array, owner, i));
440
441















144
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
442















144
            writer.writeBits(0, i);
443















144
            arrayWrite(array, owner, writer);
444


























































































144
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
445
446















144
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
447









































































































144
            ASSERT_EQ(0, reader.readBits(i));
448















288
            ArrayT readArray;
449















144
            arrayRead(readArray, owner, reader);
450


























































































144
            ASSERT_EQ(array, readArray);
451
452






























144
            testArrayCopiesAndMoves(array);
453
        }
454
    }
455
456
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE,
457
            typename std::enable_if<!ARRAY_TRAITS::IS_BITSIZEOF_CONSTANT, int>::type = 0>
458
30
    void testArrayImplicit(const RAW_ARRAY&, size_t, OWNER_TYPE&)
459
    {
460
        // implicit array not allowed for types with non-constant bitsize, so skip the test
461
30
    }
462
463
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
464
27
    void testPackedArrayNormal(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
465
    {
466
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::NORMAL, ARRAY_EXPRESSIONS>;
467
468







243
        for (uint8_t i = 0; i < 8; ++i)
469
        {
470







432
            ArrayT array(rawArray);
471
472







216
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
473







216
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
474
            {
475










































80
                ASSERT_EQ(expectedBitSize, bitSize);
476
            }
477

















































216
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
478
479







216
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
480







216
            writer.writeBits(0, i);
481







216
            arrayWritePacked(array, owner, writer);
482










































216
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
483
484







216
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
485

















































216
            ASSERT_EQ(0, reader.readBits(i));
486







432
            ArrayT readArray;
487







216
            arrayReadPacked(readArray, owner, reader, rawArray.size());
488










































216
            ASSERT_EQ(array, readArray);
489
490














216
            testArrayCopiesAndMoves(array);
491
        }
492
    }
493
494
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
495
27
    void testPackedArrayAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
496
    {
497
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::AUTO, ARRAY_EXPRESSIONS>;
498
499







243
        for (uint8_t i = 0; i < 8; ++i)
500
        {
501







432
            ArrayT array(rawArray);
502
503







216
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
504







216
            if (expectedBitSize != UNKNOWN_BIT_SIZE)
505
            {
506










































80
                ASSERT_EQ(expectedBitSize, bitSize);
507
            }
508

















































216
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
509
510







216
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
511







216
            writer.writeBits(0, i);
512







216
            arrayWritePacked(array, owner, writer);
513










































216
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
514
515







216
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
516

















































216
            ASSERT_EQ(0, reader.readBits(i));
517







432
            ArrayT readArray;
518







216
            arrayReadPacked(readArray, owner, reader);
519










































216
            ASSERT_EQ(array, readArray);
520
521














216
            testArrayCopiesAndMoves(array);
522
        }
523
    }
524
525
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
526
27
    void testPackedArrayAligned(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
527
    {
528
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED, ARRAY_EXPRESSIONS>;
529
530







243
        for (uint8_t i = 0; i < 8; ++i)
531
        {
532







432
            ArrayT array(rawArray);
533
534







216
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
535














216
            if (expectedBitSize != UNKNOWN_BIT_SIZE && i == 0)
536
            {
537










































10
                ASSERT_EQ(expectedBitSize, bitSize);
538
            }
539

















































216
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
540
541







216
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
542







216
            writer.writeBits(0, i);
543







216
            arrayWritePacked(array, owner, writer);
544










































216
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
545
546







216
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
547

















































216
            ASSERT_EQ(0, reader.readBits(i));
548







432
            ArrayT readArray;
549







216
            arrayReadPacked(readArray, owner, reader, rawArray.size());
550










































216
            ASSERT_EQ(array, readArray);
551
552














216
            testArrayCopiesAndMoves(array);
553
        }
554
    }
555
556
    template <typename ARRAY_TRAITS, typename RAW_ARRAY, typename ARRAY_EXPRESSIONS, typename OWNER_TYPE>
557
27
    void testPackedArrayAlignedAuto(const RAW_ARRAY& rawArray, size_t expectedBitSize, OWNER_TYPE& owner)
558
    {
559
        using ArrayT = Array<RAW_ARRAY, ARRAY_TRAITS, ArrayType::ALIGNED_AUTO, ARRAY_EXPRESSIONS>;
560
561







243
        for (uint8_t i = 0; i < 8; ++i)
562
        {
563







432
            ArrayT array(rawArray);
564
565







216
            const size_t bitSize = arrayBitSizeOfPacked(array, owner, i);
566














216
            if (expectedBitSize != UNKNOWN_BIT_SIZE && i == 0)
567
            {
568










































10
                ASSERT_EQ(expectedBitSize, bitSize);
569
            }
570

















































216
            ASSERT_EQ(i + bitSize, arrayInitializeOffsetsPacked(array, owner, i));
571
572







216
            BitStreamWriter writer(m_byteBuffer.data(), m_byteBuffer.size());
573







216
            writer.writeBits(0, i);
574







216
            arrayWritePacked(array, owner, writer);
575










































216
            ASSERT_EQ(i + bitSize, writer.getBitPosition());
576
577







216
            BitStreamReader reader(m_byteBuffer.data(), writer.getBitPosition(), BitsTag());
578

















































216
            ASSERT_EQ(0, reader.readBits(i));
579







432
            ArrayT readArray;
580







216
            arrayReadPacked(readArray, owner, reader);
581










































216
            ASSERT_EQ(array, readArray);
582
583














216
            testArrayCopiesAndMoves(array);
584
        }
585
    }
586
587
    template <typename ARRAY>
588
3248
    void testArrayCopiesAndMoves(const ARRAY& array)
589
    {
590





















































































































6496
        ARRAY arrayCopy(array);
591






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array, arrayCopy);
592






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array.getRawArray(), arrayCopy.getRawArray());
593
594























































































































6496
        ARRAY arrayCopyAssigned;
595





















































































































3248
        arrayCopyAssigned = array;
596






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array, arrayCopyAssigned);
597






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array.getRawArray(), arrayCopyAssigned.getRawArray());
598
599





















































































































6496
        const ARRAY arrayMoved = std::move(arrayCopy);
600






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array, arrayMoved);
601






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array.getRawArray(), arrayMoved.getRawArray());
602
603























































































































6496
        ARRAY arrayMoveAssigned;
604
3248
        arrayMoveAssigned = std::move(arrayCopyAssigned);
605






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array, arrayMoveAssigned);
606






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array.getRawArray(), arrayMoveAssigned.getRawArray());
607
608










































































































































































































































6496
        ARRAY arrayCopyWithPropagateAllocator(PropagateAllocator, array, std::allocator<uint8_t>());
609






























































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array, arrayCopyWithPropagateAllocator);
610



















































































































































































































































































































































































































































































































































































































































































































































































































































3248
        ASSERT_EQ(array.getRawArray(), arrayCopyWithPropagateAllocator.getRawArray());
611
    }
612
613
    static const size_t AUTO_LENGTH_BIT_SIZE = 8;
614
    static const size_t UNKNOWN_BIT_SIZE = std::numeric_limits<size_t>::max();
615
616
    std::array<uint8_t, 256> m_byteBuffer;
617
};
618
619


776
TEST_F(ArrayTest, intField4Array)
620
{
621
1
    const size_t NUM_BITS = 4;
622
    std::vector<int8_t> rawArray = {
623
            -static_cast<int8_t>(1U << (NUM_BITS - 1)),
624
            7,
625
2
            static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
626
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(rawArray, NUM_BITS);
627
628
    // empty
629
1
    testArray<BitFieldArrayTraits<int8_t, NUM_BITS>>(std::vector<int8_t>(), NUM_BITS);
630
1
}
631
632


776
TEST_F(ArrayTest, intField12Array)
633
{
634
1
    constexpr size_t NUM_BITS = 12;
635
    std::vector<int16_t> rawArray = {
636
            -static_cast<int16_t>(1U << (NUM_BITS - 1)),
637
            7,
638
2
            static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
639
1
    testArray<BitFieldArrayTraits<int16_t, NUM_BITS>>(rawArray, NUM_BITS);
640
1
}
641
642


776
TEST_F(ArrayTest, intField20Array)
643
{
644
1
    constexpr size_t NUM_BITS = 20;
645
    std::vector<int32_t> rawArray = {
646
            -static_cast<int32_t>(1U << (NUM_BITS - 1)),
647
            7,
648
2
            static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
649
1
    testArray<BitFieldArrayTraits<int32_t, NUM_BITS>>(rawArray, NUM_BITS);
650
1
}
651
652


776
TEST_F(ArrayTest, intField36Array)
653
{
654
1
    constexpr size_t NUM_BITS = 36;
655
    std::vector<int64_t> rawArray = {
656
            -static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)),
657
            7,
658
2
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
659
1
    testArray<BitFieldArrayTraits<int64_t, NUM_BITS>>(rawArray, NUM_BITS);
660
1
}
661
662


776
TEST_F(ArrayTest, bitField4Array)
663
{
664
1
    constexpr size_t NUM_BITS = 4;
665
2
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
666
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(rawArray, NUM_BITS);
667
668
    // empty
669
1
    testArray<BitFieldArrayTraits<uint8_t, NUM_BITS>>(std::vector<uint8_t>(), NUM_BITS);
670
1
}
671
672


776
TEST_F(ArrayTest, bitField12Array)
673
{
674
1
    constexpr size_t NUM_BITS = 12;
675
2
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
676
1
    testArray<BitFieldArrayTraits<uint16_t, NUM_BITS>>(rawArray, NUM_BITS);
677
1
}
678
679


776
TEST_F(ArrayTest, bitField20Array)
680
{
681
1
    constexpr size_t NUM_BITS = 20;
682
2
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
683
1
    testArray<BitFieldArrayTraits<uint32_t, NUM_BITS>>(rawArray, NUM_BITS);
684
1
}
685
686


776
TEST_F(ArrayTest, bitField36Array)
687
{
688
1
    constexpr size_t NUM_BITS = 36;
689
2
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
690
1
    testArray<BitFieldArrayTraits<uint64_t, NUM_BITS>>(rawArray, NUM_BITS);
691
1
}
692
693


776
TEST_F(ArrayTest, dynamicIntField4Array)
694
{
695
1
    constexpr size_t NUM_BITS = 4;
696
    std::vector<int8_t> rawArray = {
697
            -static_cast<int8_t>(1U << (NUM_BITS - 1)),
698
            7,
699
2
            static_cast<int8_t>(1U << (NUM_BITS - 1)) - 1};
700
2
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
701
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
702
703
    // empty
704
2
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
705
1
            std::vector<int8_t>(), NUM_BITS);
706
1
}
707
708


776
TEST_F(ArrayTest, dynamicIntField8Array)
709
{
710
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
711
2
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
712
2
    testArray<DynamicBitFieldArrayTraits<int8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
713
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
714
1
}
715
716


776
TEST_F(ArrayTest, dynamicIntField12Array)
717
{
718
1
    constexpr size_t NUM_BITS = 12;
719
    std::vector<int16_t> rawArray = {
720
            -static_cast<int16_t>(1U << (NUM_BITS - 1)),
721
            7,
722
2
            static_cast<int16_t>(1U << (NUM_BITS - 1)) - 1};
723
1
    testArray<DynamicBitFieldArrayTraits<int16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
724
1
}
725
726


776
TEST_F(ArrayTest, dynamicIntField20Array)
727
{
728
1
    constexpr size_t NUM_BITS = 20;
729
    std::vector<int32_t> rawArray = {
730
            -static_cast<int32_t>(1U << (NUM_BITS - 1)),
731
            7,
732
2
            static_cast<int32_t>(1U << (NUM_BITS - 1)) - 1};
733
2
    testArray<DynamicBitFieldArrayTraits<int32_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
734
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
735
1
}
736
737


776
TEST_F(ArrayTest, dynamicIntField36Array)
738
{
739
1
    constexpr size_t NUM_BITS = 36;
740
    std::vector<int64_t> rawArray = {
741
            -static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)),
742
            7,
743
2
            static_cast<int64_t>(UINT64_C(1) << (NUM_BITS - 1)) - 1};
744
1
    testArray<DynamicBitFieldArrayTraits<int64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
745
1
}
746
747


776
TEST_F(ArrayTest, dynamicBitField4Array)
748
{
749
1
    constexpr size_t NUM_BITS = 4;
750
2
    std::vector<uint8_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
751
2
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
752
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
753
754
    // empty
755
2
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(
756
1
            std::vector<uint8_t>(), NUM_BITS);
757
1
}
758
759


776
TEST_F(ArrayTest, dynamicBitField8Array)
760
{
761
1
    constexpr size_t NUM_BITS = 8; // aligned to allow implicit array
762
2
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
763
2
    testArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
764
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
765
1
}
766
767


776
TEST_F(ArrayTest, dynamicBitField12Array)
768
{
769
1
    constexpr size_t NUM_BITS = 12;
770
2
    std::vector<uint16_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
771
1
    testArray<DynamicBitFieldArrayTraits<uint16_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
772
1
}
773
774


776
TEST_F(ArrayTest, dynamicBitField20Array)
775
{
776
1
    constexpr size_t NUM_BITS = 20;
777
2
    std::vector<uint32_t> rawArray = {0, 7, (1U << NUM_BITS) - 1};
778
2
    testArray<DynamicBitFieldArrayTraits<uint32_t, ElementBitSizeWithOwner>>(rawArray, NUM_BITS,
779
1
            ArrayTestOwnerWithBitSize(NUM_BITS));
780
1
}
781
782


776
TEST_F(ArrayTest, dynamicBitField36Array)
783
{
784
1
    constexpr size_t NUM_BITS = 36;
785
2
    std::vector<uint64_t> rawArray = {0, 7, (UINT64_C(1) << NUM_BITS) - 1};
786
1
    testArray<DynamicBitFieldArrayTraits<uint64_t, ElementBitSizeWithoutOwner<NUM_BITS>>>(rawArray, NUM_BITS);
787
1
}
788
789


776
TEST_F(ArrayTest, stdInt8Array)
790
{
791
2
    std::vector<int8_t> rawArray = {INT8_MIN, 7, INT8_MAX};
792
1
    testArray<StdIntArrayTraits<int8_t>>(rawArray, 8);
793
794
    // empty
795
1
    testArray<StdIntArrayTraits<int8_t>>(std::vector<int8_t>(), 8);
796
1
}
797
798


776
TEST_F(ArrayTest, stdInt16Array)
799
{
800
2
    std::vector<int16_t> rawArray = {INT16_MIN, 7, INT16_MAX};
801
1
    testArray<StdIntArrayTraits<int16_t>>(rawArray, 16);
802
1
}
803
804


776
TEST_F(ArrayTest, stdInt32Array)
805
{
806
2
    std::vector<int32_t> rawArray = {INT32_MIN, 7, INT32_MAX};
807
1
    testArray<StdIntArrayTraits<int32_t>>(rawArray, 32);
808
1
}
809
810


776
TEST_F(ArrayTest, stdInt64Array)
811
{
812
2
    std::vector<int64_t> rawArray = {INT64_MIN, 7, INT64_MAX};
813
1
    testArray<StdIntArrayTraits<int64_t>>(rawArray, 64);
814
1
}
815
816


776
TEST_F(ArrayTest, stdUInt8Array)
817
{
818
2
    std::vector<uint8_t> rawArray = {0, 7, UINT8_MAX};
819
1
    testArray<StdIntArrayTraits<uint8_t>>(rawArray, 8);
820
821
    // empty
822
1
    testArray<StdIntArrayTraits<uint8_t>>(std::vector<uint8_t>(), 8);
823
1
}
824
825


776
TEST_F(ArrayTest, stdUInt16Array)
826
{
827
2
    std::vector<uint16_t> rawArray = {0, 7, UINT16_MAX};
828
1
    testArray<StdIntArrayTraits<uint16_t>>(rawArray, 16);
829
1
}
830
831


776
TEST_F(ArrayTest, stdUInt32Array)
832
{
833
2
    std::vector<uint32_t> rawArray = {0, 7, UINT32_MAX};
834
1
    testArray<StdIntArrayTraits<uint32_t>>(rawArray, 32);
835
1
}
836
837


776
TEST_F(ArrayTest, stdUInt64Array)
838
{
839
2
    std::vector<uint64_t> rawArray = {0, 7, UINT64_MAX};
840
1
    testArray<StdIntArrayTraits<uint64_t>>(rawArray, 64);
841
1
}
842
843


776
TEST_F(ArrayTest, varInt16Array)
844
{
845
2
    std::vector<int16_t> rawArray = {static_cast<int16_t>(1U << 5U), static_cast<int16_t>(1U << (5U + 8))};
846
1
    const size_t bitSize = 8 * (1 + 2);
847
1
    testArray<VarIntNNArrayTraits<int16_t>>(rawArray, bitSize, bitSize);
848
849
    // empty
850
1
    testArray<VarIntNNArrayTraits<int16_t>>(std::vector<int16_t>(), 0, 0);
851
1
}
852
853


776
TEST_F(ArrayTest, varInt32Array)
854
{
855
    std::vector<int32_t> rawArray = {
856
            static_cast<int32_t>(1U << 5U),
857
            static_cast<int32_t>(1U << (5U + 7)),
858
            static_cast<int32_t>(1U << (5U + 7 + 7)),
859
2
            static_cast<int32_t>(1U << (5U + 7 + 7 + 8))};
860
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
861
1
    testArray<VarIntNNArrayTraits<int32_t>>(rawArray, bitSize, bitSize);
862
863
    // empty
864
1
    testArray<VarIntNNArrayTraits<int32_t>>(std::vector<int32_t>(), 0, 0);
865
1
}
866
867


776
TEST_F(ArrayTest, varInt64Array)
868
{
869
    std::vector<int64_t> rawArray = {
870
            static_cast<int64_t>(UINT64_C(1) << 5U),
871
            static_cast<int64_t>(UINT64_C(1) << (5U + 7)),
872
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7)),
873
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7)),
874
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7)),
875
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7)),
876
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7)),
877
2
            static_cast<int64_t>(UINT64_C(1) << (5U + 7 + 7 + 7 + 7 + 7 + 7 + 8))};
878
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
879
1
    testArray<VarIntNNArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
880
881
    // empty
882
1
    testArray<VarIntNNArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
883
1
}
884
885


776
TEST_F(ArrayTest, varUInt16Array)
886
{
887
2
    std::vector<uint16_t> rawArray = {1U << 6U, 1U << (6U + 8)};
888
1
    const size_t bitSize = 8 * (1 + 2);
889
1
    testArray<VarIntNNArrayTraits<uint16_t>>(rawArray, bitSize, bitSize);
890
891
    // empty
892
1
    testArray<VarIntNNArrayTraits<uint16_t>>(std::vector<uint16_t>(), 0, 0);
893
1
}
894
895


776
TEST_F(ArrayTest, varUInt32Array)
896
{
897
2
    std::vector<uint32_t> rawArray = {1U << 6U, 1U << (6U + 7), 1U << (6U + 7 + 7), 1U << (6U + 7 + 7 + 8)};
898
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4);
899
1
    testArray<VarIntNNArrayTraits<uint32_t>>(rawArray, bitSize, bitSize);
900
901
    // empty
902
1
    testArray<VarIntNNArrayTraits<uint32_t>>(std::vector<uint32_t>(), 0, 0);
903
1
}
904
905


776
TEST_F(ArrayTest, varUInt64Array)
906
{
907
    std::vector<uint64_t> rawArray = {
908
            UINT64_C(1) << 6U,
909
            UINT64_C(1) << (6U + 7),
910
            UINT64_C(1) << (6U + 7 + 7),
911
            UINT64_C(1) << (6U + 7 + 7 + 7),
912
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
913
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
914
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
915
2
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8)};
916
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
917
1
    testArray<VarIntNNArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
918
919
    // empty
920
1
    testArray<VarIntNNArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
921
1
}
922
923


776
TEST_F(ArrayTest, varIntArray)
924
{
925
2
    std::vector<int64_t> rawArray;
926
    // 1 byte
927
1
    rawArray.push_back(0);
928
1
    rawArray.push_back(-1);
929
1
    rawArray.push_back(1);
930
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 6U) + 1);
931
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 6U) - 1);
932
    // 2 bytes
933
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 13U) + 1);
934
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 13U) - 1);
935
    // 3 bytes
936
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 20U) + 1);
937
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 20U) - 1);
938
    // 4 bytes
939
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 27U) + 1);
940
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 27U) - 1);
941
    // 5 bytes
942
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 34U) + 1);
943
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 34U) - 1);
944
    // 6 bytes
945
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 41U) + 1);
946
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 41U) - 1);
947
    // 7 bytes
948
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 48U) + 1);
949
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 48U) - 1);
950
    // 8 bytes
951
1
    rawArray.push_back(-static_cast<int64_t>(UINT64_C(1) << 55U) + 1);
952
1
    rawArray.push_back(static_cast<int64_t>(UINT64_C(1) << 55U) - 1);
953
    // 9 bytes
954
1
    rawArray.push_back(INT64_MIN + 1);
955
1
    rawArray.push_back(INT64_MAX);
956
    // 1 byte - special case, INT64_MIN stored as -0
957
1
    rawArray.push_back(INT64_MIN);
958
1
    const size_t bitSize = 8 * (3 + 2 * (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) + 1);
959
1
    testArray<VarIntArrayTraits<int64_t>>(rawArray, bitSize, bitSize);
960
961
    // empty
962
1
    testArray<VarIntArrayTraits<int64_t>>(std::vector<int64_t>(), 0, 0);
963
1
}
964
965


776
TEST_F(ArrayTest, varUIntArray)
966
{
967
2
    std::vector<uint64_t> rawArray;
968
    // 1 byte
969
1
    rawArray.push_back(0);
970
1
    rawArray.push_back(1);
971
1
    rawArray.push_back((UINT64_C(1) << 7U) - 1);
972
    // 2 bytes
973
1
    rawArray.push_back((UINT64_C(1) << 14U) - 1);
974
    // 3 bytes
975
1
    rawArray.push_back((UINT64_C(1) << 21U) - 1);
976
    // 4 bytes
977
1
    rawArray.push_back((UINT64_C(1) << 28U) - 1);
978
    // 5 bytes
979
1
    rawArray.push_back((UINT64_C(1) << 35U) - 1);
980
    // 6 bytes
981
1
    rawArray.push_back((UINT64_C(1) << 42U) - 1);
982
    // 7 bytes
983
1
    rawArray.push_back((UINT64_C(1) << 49U) - 1);
984
    // 8 bytes
985
1
    rawArray.push_back((UINT64_C(1) << 56U) - 1);
986
    // 9 bytes
987
1
    rawArray.push_back(UINT64_MAX);
988
1
    const size_t bitSize = 8 * (2 + (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9));
989
1
    testArray<VarIntArrayTraits<uint64_t>>(rawArray, bitSize, bitSize);
990
991
    // empty
992
1
    testArray<VarIntArrayTraits<uint64_t>>(std::vector<uint64_t>(), 0, 0);
993
1
}
994
995


776
TEST_F(ArrayTest, varSizeArray)
996
{
997
    std::vector<uint32_t> rawArray = {
998
            UINT32_C(1) << 6U,
999
            UINT32_C(1) << (6U + 7),
1000
            UINT32_C(1) << (6U + 7 + 7),
1001
            UINT32_C(1) << (6U + 7 + 7 + 7),
1002
2
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8)};
1003
1
    const size_t bitSize = 8 * (1 + 2 + 3 + 4 + 5);
1004
1
    testArray<VarSizeArrayTraits>(rawArray, bitSize, bitSize);
1005
1006
    // empty
1007
1
    testArray<VarSizeArrayTraits>(std::vector<uint32_t>(), 0, 0);
1008
1
}
1009
1010


776
TEST_F(ArrayTest, float16Array)
1011
{
1012
1
    const size_t elementBitSize = 16;
1013
2
    std::vector<float> rawArray = {-9.0, 0.0,  10.0};
1014
1
    testArray<Float16ArrayTraits>(rawArray, elementBitSize);
1015
1016
    // empty
1017
1
    testArray<Float16ArrayTraits>(std::vector<float>(), elementBitSize);
1018
1
}
1019
1020


776
TEST_F(ArrayTest, float32Array)
1021
{
1022
1
    const size_t elementBitSize = 32;
1023
2
    std::vector<float> rawArray = {-9.0, 0.0,  10.0};
1024
1
    testArray<Float32ArrayTraits>(rawArray, elementBitSize);
1025
1026
    // empty
1027
1
    testArray<Float32ArrayTraits>(std::vector<float>(), elementBitSize);
1028
1
}
1029
1030


776
TEST_F(ArrayTest, float64Array)
1031
{
1032
1
    const size_t elementBitSize = 64;
1033
2
    std::vector<double> rawArray = {-9.0, 0.0, 10.0};
1034
1
    testArray<Float64ArrayTraits>(rawArray, elementBitSize);
1035
1036
    // empty
1037
1
    testArray<Float64ArrayTraits>(std::vector<double>(), elementBitSize);
1038
1
}
1039
1040


776
TEST_F(ArrayTest, boolArray)
1041
{
1042
1
    const size_t elementBitSize = 1;
1043
2
    std::vector<bool> rawArray = {false, true};
1044
1
    testArray<BoolArrayTraits>(rawArray, elementBitSize);
1045
1046
    // empty
1047
1
    testArray<BoolArrayTraits>(std::vector<bool>(), elementBitSize);
1048
1
}
1049
1050


776
TEST_F(ArrayTest, bytesArray)
1051
{
1052
1
    const size_t bytesLengthBitSize = 8;
1053
1
    const size_t bytesBitSize = 2 * 8;
1054
1
    const size_t elementBitSize = bytesLengthBitSize + bytesBitSize;
1055


2
    std::vector<std::vector<uint8_t>> rawArray = {{ {{ 1, 255 }}, {{ 127, 128 }} }};
1056
1
    testArray<BytesArrayTraits>(rawArray, elementBitSize);
1057
1058
    // empty
1059
1
    testArray<BytesArrayTraits>(std::vector<std::vector<uint8_t>>(), elementBitSize);
1060
1
}
1061
1062


776
TEST_F(ArrayTest, stringArray)
1063
{
1064
1
    const size_t stringLengthBitSize = 8;
1065
1
    const size_t stringBitSize = (sizeof("StringX") - 1) * 8; // without terminating character
1066
1
    const size_t elementBitSize = stringLengthBitSize + stringBitSize;
1067



2
    std::vector<std::string> rawArray = {"String0", "String1", "String2"};
1068
1
    testArray<StringArrayTraits>(rawArray, elementBitSize);
1069
1070
    // empty
1071
1
    testArray<StringArrayTraits>(std::vector<std::string>(), 0);
1072
1
}
1073
1074


776
TEST_F(ArrayTest, bitBufferArray)
1075
{
1076
1
    const size_t bitBufferLengthBitSize = 8;
1077
1
    const size_t bitBufferBitSize = 10;
1078
1
    const size_t elementBitSize = bitBufferLengthBitSize + bitBufferBitSize;
1079
    std::vector<BitBuffer> rawArray = {BitBuffer(bitBufferBitSize), BitBuffer(bitBufferBitSize),
1080



2
            BitBuffer(bitBufferBitSize)};
1081
1
    testArray<BitBufferArrayTraits>(rawArray, elementBitSize);
1082
1083
    // empty
1084
1
    testArray<BitBufferArrayTraits>(std::vector<BitBuffer>(), 0);
1085
1
}
1086
1087


776
TEST_F(ArrayTest, enumArray)
1088
{
1089
2
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1090
1
    const size_t elementBitSize = 8;
1091
1
    testArray<EnumArrayTraits<ArrayEnum>>(rawArray, elementBitSize);
1092
1093
    // empty
1094
1
    testArray<EnumArrayTraits<ArrayEnum>>(std::vector<ArrayEnum>(), elementBitSize);
1095
1096

2
    std::vector<ArrayEnum> invalidRawArray = {static_cast<ArrayEnum>(10)};
1097










2
    ASSERT_THROW(testArray<EnumArrayTraits<ArrayEnum>>(invalidRawArray, elementBitSize), CppRuntimeException);
1098
}
1099
1100


776
TEST_F(ArrayTest, bitmaskArray)
1101
{
1102
    std::vector<ArrayBitmask> rawArray = {ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE,
1103
2
            ArrayBitmask::Values::CREATE};
1104
1
    const size_t elementBitSize = 8;
1105
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray, elementBitSize);
1106
1107
    // empty
1108
1
    testArray<BitmaskArrayTraits<ArrayBitmask>>(std::vector<ArrayBitmask>(), elementBitSize);
1109
1
}
1110
1111


776
TEST_F(ArrayTest, objectArray)
1112
{
1113
2
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1114
1
    testArrayInitializeElements<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>>(rawArray);
1115
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1116
1
            ArrayObjectArrayExpressions>(rawArray, 31);
1117
1118
    // empty
1119
    testArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1120
1
            ArrayObjectArrayExpressions>(std::vector<ArrayObject>(), 31);
1121
1
}
1122
1123


776
TEST_F(ArrayTest, stdInt8PackedArray)
1124
{
1125
2
    std::vector<int8_t> rawArray = { -4, -3, -1, 0, 2, 4, 6, 8, 10, 10, 11 };
1126
1
    testPackedArray<StdIntArrayTraits<int8_t>>(rawArray);
1127
1
}
1128
1129


776
TEST_F(ArrayTest, stdInt64PackedArray)
1130
{
1131
    // will not be packed
1132
2
    std::vector<int64_t> rawArray = { INT64_MIN, 1, -1, INT64_MAX };
1133
1
    testPackedArray<StdIntArrayTraits<int64_t>>(rawArray);
1134
1
}
1135
1136


776
TEST_F(ArrayTest, stdUInt64PackedArray)
1137
{
1138
    // will have maxBitNumber 62 bits
1139
2
    std::vector<uint64_t> rawArray = { 0, INT64_MAX / 2, 100, 200, 300, 400, 500, 600, 700 };
1140
1
    testPackedArray<StdIntArrayTraits<uint64_t>>(rawArray);
1141
1
}
1142
1143


776
TEST_F(ArrayTest, bitField64PackedArray)
1144
{
1145
    using ArrayTraits = BitFieldArrayTraits<uint64_t, 64>;
1146
1147
    // none-zero delta
1148
2
    std::vector<uint64_t> rawArray1 = {10, 11, 12};
1149
1
    const size_t array1MaxDeltaBitSize = 1;
1150
1
    const size_t array1BitSizeOf = calcPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1151
1
    const size_t array1AlignedBitSizeOf = calcAlignedPackedBitSize(64, rawArray1.size(), array1MaxDeltaBitSize);
1152
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1153
1154
    // zero delta
1155
2
    std::vector<uint64_t> rawArray2 = {10, 10, 10};
1156
1
    const size_t array2BitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64;
1157
    const size_t array2AlignedBitSizeOf = PACKING_DESCRIPTOR_BITSIZE + 64 +
1158
1
            /* alignment before element 2 */ (8 - PACKING_DESCRIPTOR_BITSIZE);
1159
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1160
1161
    // one-element array
1162
2
    std::vector<uint64_t> rawArray3 = {10};
1163
1
    const size_t array3BitSizeOf = 1 + 64;
1164
1
    const size_t array3AlignedBitSizeOf = 1 + 64; // no alignment before first element, no more elements
1165
1
    testPackedArray<ArrayTraits>(rawArray3, array3BitSizeOf, array3AlignedBitSizeOf);
1166
1167
    // empty array
1168
2
    std::vector<uint64_t> rawArray4 = {};
1169
1
    const size_t array4BitSizeOf = 0;
1170
1
    const size_t array4AlignedBitSizeOf = 0;
1171
1
    testPackedArray<ArrayTraits>(rawArray4, array4BitSizeOf, array4AlignedBitSizeOf);
1172
1173
    // packing not enabled, delta is too big
1174

1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{0, UINT64_MAX});
1175

1
    testPackedArray<ArrayTraits>(std::vector<uint64_t>{UINT64_MAX, UINT64_MAX / 2, 0});
1176
1177
    // will have maxBitNumber 62 bits
1178
2
    testPackedArray<ArrayTraits>(
1179
1
            std::vector<uint64_t>{0, static_cast<uint64_t>(INT64_MAX / 2), 100, 200, 300, 400, 500, 600, 700});
1180
1
}
1181
1182


776
TEST_F(ArrayTest, bitField8PackedArray)
1183
{
1184
    using ArrayTraits = BitFieldArrayTraits<uint8_t, 8>;
1185
1186
    // will not be packed because unpacked 8bit values will be more efficient
1187
2
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1188
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1189
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1190
1
    testPackedArray<ArrayTraits>(rawArray1, array1BitSizeOf, array1AlignedBitSizeOf);
1191
1192
    // will not be packed because unpacked 8bit values will be more efficient
1193
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1194
    std::vector<uint8_t> rawArray2 =
1195
2
            {UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1196
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1197
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1198
1
    testPackedArray<ArrayTraits>(rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1199
1
}
1200
1201


776
TEST_F(ArrayTest, intField64PackedArray)
1202
{
1203
    using ArrayTraits = BitFieldArrayTraits<int64_t, 64>;
1204
1205

1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, 11, -12});
1206

1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{-10, -10, -10}); // zero delta
1207
1208
1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{}); // empty
1209

1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{10}); // single element
1210
1211
    // packing not enabled, delta is too big
1212

1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, INT64_MAX});
1213

1
    testPackedArray<ArrayTraits>(std::vector<int64_t>{INT64_MIN, 0, INT64_MAX});
1214
1
}
1215
1216


776
TEST_F(ArrayTest, intField16PackedArray)
1217
{
1218
    using ArrayTraits = BitFieldArrayTraits<int16_t, 16>;
1219
1220
    // will not be packed because unpacked 16bit values will be more efficient
1221
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1222
2
    std::vector<int16_t> rawArray = {INT16_MIN, -1, 10, 20, 30, 40}; // max_bit_number 15, delta needs 16 bits
1223
1
    const size_t unpackedBitSizeOf = 1 + 6 * 16;
1224
1
    const size_t unpackedAlignedBitSizeOf = 1 + 16 + /* alignment */ 7 + 5 * 16;
1225
1
    testPackedArray<ArrayTraits>(rawArray, unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1226
1
}
1227
1228


776
TEST_F(ArrayTest, dynamicBitField8PackedArray)
1229
{
1230
    // will not be packed because unpacked 8bit values will be more efficient
1231
2
    std::vector<uint8_t> rawArray1 = {UINT8_MAX, 0, 10, 20, 30, 40}; // max_bit_number 8, delta needs 9 bits
1232
1
    const size_t array1BitSizeOf = 1 + 6 * 8;
1233
1
    const size_t array1AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1234
2
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithOwner>>(
1235
1
            rawArray1, array1BitSizeOf, array1AlignedBitSizeOf, ArrayTestOwnerWithBitSize(8));
1236
1237
    // will not be packed because unpacked 8bit values will be more efficient
1238
    // (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
1239
    std::vector<uint8_t> rawArray2 =
1240
2
            {UINT8_MAX, UINT8_MAX / 2 + 1, 10, 20, 30, 40}; // max_bit_number 7, delta needs 8 bits
1241
1
    const size_t array2BitSizeOf = 1 + 6 * 8;
1242
1
    const size_t array2AlignedBitSizeOf = 1 + 8 + /* alignment */ 7 + 5 * 8;
1243
2
    testPackedArray<DynamicBitFieldArrayTraits<uint8_t, ElementBitSizeWithoutOwner<8>>>(
1244
1
            rawArray2, array2BitSizeOf, array2AlignedBitSizeOf);
1245
1
}
1246
1247


776
TEST_F(ArrayTest, varUInt64PackedArray)
1248
{
1249
    std::vector<uint64_t> rawArray = {
1250
            UINT64_C(1) << 6U,
1251
            UINT64_C(1) << (6U + 7),
1252
            UINT64_C(1) << (6U + 7 + 7),
1253
            UINT64_C(1) << (6U + 7 + 7 + 7),
1254
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7),
1255
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7),
1256
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7),
1257
2
            UINT64_C(1) << (6U + 7 + 7 + 7 + 7 + 7 + 7 + 8)};
1258
1
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(rawArray);
1259
1260
2
    std::vector<uint64_t> unpackedRawArray = {UINT64_C(5000000), 0, 0, 0, 0, 0, 0};
1261
1
    const size_t unpackedBitSizeOf = 1 + 32 + 6 * 8;
1262
1
    const size_t unpackedAlignedBitSizeOf = 1 + 32 + /* alignment */ 7 + 6 * 8;
1263
2
    testPackedArray<VarIntNNArrayTraits<uint64_t>>(unpackedRawArray,
1264
1
            unpackedBitSizeOf, unpackedAlignedBitSizeOf);
1265
1
}
1266
1267


776
TEST_F(ArrayTest, varSizePackedArray)
1268
{
1269
    std::vector<uint32_t> rawArray = {
1270
            UINT32_C(1) << 6U,
1271
            UINT32_C(1) << (6U + 7),
1272
            UINT32_C(1) << (6U + 7 + 7),
1273
            UINT32_C(1) << (6U + 7 + 7 + 7),
1274
2
            UINT32_C(1) << (1U + 7 + 7 + 7 + 8)};
1275
1
    testPackedArray<VarSizeArrayTraits>(rawArray);
1276
1
}
1277
1278


776
TEST_F(ArrayTest, enumPackedArray)
1279
{
1280
2
    std::vector<ArrayEnum> rawArray = {ArrayEnum::VALUE1, ArrayEnum::VALUE2, ArrayEnum::VALUE3};
1281
1
    testPackedArray<EnumArrayTraits<ArrayEnum>>(rawArray);
1282
1
}
1283
1284


776
TEST_F(ArrayTest, bitmaskPackedArray)
1285
{
1286
    std::vector<ArrayBitmask> rawArray = {ArrayBitmask::Values::READ, ArrayBitmask::Values::WRITE,
1287
2
            ArrayBitmask::Values::CREATE};
1288
1
    testPackedArray<BitmaskArrayTraits<ArrayBitmask>>(rawArray);
1289
1
}
1290
1291


776
TEST_F(ArrayTest, objectPackedArray)
1292
{
1293
2
    std::vector<ArrayObject> rawArray = {ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)};
1294
    testPackedArray<ObjectArrayTraits<ArrayObject, ArrayObjectElementFactory>, std::vector<ArrayObject>,
1295
1
            ArrayObjectArrayExpressions>(rawArray);
1296
1
}
1297
1298


776
TEST_F(ArrayTest, createOptionalArray)
1299
{
1300
    using ArrayT = Array<std::vector<uint8_t>, BitFieldArrayTraits<uint8_t, 8>, ArrayType::NORMAL>;
1301
2
    InplaceOptionalHolder<ArrayT> optionalArray = createOptionalArray<ArrayT>(NullOpt);
1302



1
    ASSERT_FALSE(optionalArray.hasValue());
1303
1304

2
    const std::vector<uint8_t> array = {0, 7, UINT8_MAX};
1305

1
    optionalArray = createOptionalArray<ArrayT>(array);
1306



1
    ASSERT_TRUE(optionalArray.hasValue());
1307




1
    ASSERT_EQ(array, optionalArray->getRawArray());
1308
}
1309
1310

2316
} // namespace zserio